<?php

namespace app\common\model;

use app\admin\model\RecoveryCustom;
use app\admin\model\Region;
use fast\Random;
use think\Config;
use think\Db;
use think\exception\PDOException;
use think\exception\ValidateException;
use think\Model;

class Order extends Model
{
    // 表名
    protected $name = 'order';
    // 开启自动写入时间戳字段
    protected $autoWriteTimestamp = 'int';
    // 定义时间戳字段名
    protected $createTime   = 'createtime';
    protected $updateTime   = 'updatetime';
    // 追加属性
    protected $append = [
        'status_text',
        'weight_type_text',
        'createtime_text',
        'deliverytime_text',
        'receivingtime_text',
        'scheduledtime_text',
        'accepttime_text',
        'successtime_text'
    ];

    public function base($query)
    {
        $query->where(['deletetime' => null]);
    }

    /**
     * 回收员接单
     * @param array $params
     * @return bool
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function orderTaking($params = [])
    {
        $id                 = !empty($params['id']) ? intval($params['id']) : false;
        $recycler_user_id   = !empty($params['recycler_user_id']) ? intval($params['recycler_user_id']) : false;

        if (!$id || !$recycler_user_id) {
            $this->error = __('Recycler or empty order');
            return false;
        }

        if (!$this->getDetail(['where' => ['id' => $id]])) {
            return false;
        }

        $row = $this->getData();
        if ($row['recycler_id']) {
            $this->error = __('Cannot take the order again');
            return false;
        }

        if (!in_array($row['status'], [0])) {
            $this->error = __('The order status is wrong and the order cannot be accepted');
            return false;
        }

        $recyclerModel  = new UserRecyclerInfo();
        if (!$recyclerModel->getDetail(['where' => ['user_id' => $recycler_user_id]])) {
            $this->error = $recyclerModel->getError();
            return false;
        }

        $recycler   = $recyclerModel->getData();
        $updData    = [
            'recycler_id'       => $recycler['id'],
            'recycler_name'     => $recycler['name'],
            'recycler_mobile'   => $recycler['mobile'],
            'status'            => 1,
            'updatetime'        => time(),
            'accepttime'        => time(),
        ];

        if ($row['region_id'] != $recycler['region_id']) {
            $this->error = __('The order has exceeded the area you manage');
            return false;
        }

        if ($this->where(['id' => $id, 'status' => 0])->update($updData)) {
            $template           = get_wechat_templates('745');
            $template['touser'] = Db::name('UserThird')->where(['platform' => 'wechat', 'apptype' => 'wechat_applet', 'user_id' => $row['user_id']])->order('id ASC')->value('openid');
            $template['page']   = 'pages/order/order-detail?order_id=' . $id;
            $template['data']   = [
                'character_string1' => [
                    'value' => $row['order_no']
                ],
                'thing2'            => [
                    'value' => '上门回收'
                ],
                'name3'             => [
                    'value' => $recycler['name']
                ],
                'phone_number6'     => [
                    'value' => $recycler['mobile']
                ],
                'time10'            => [
                    'value' => date('Y年m月d日 H:i:s')
                ],
            ];

            try {
                 wechat_factory()->subscribe_message->send($template);
            } catch (\Exception $e) {
                return true;
            }

            return true;
        }

        $this->error = __('Order failed');
        return false;
    }

    /**
     * 订单取消
     * @param array $params
     * @return bool
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function cancel($params = [])
    {
        if (!$this->getDetail($params)) {
            return false;
        }

        $row = $this->getData();
        if (!$this->where(['id' => $row['id']])->update(['status' => 6, 'updatetime' => time()])) {
            $this->error = __('Order cancellation failed');
            return false;
        }

        return true;
    }

    /**
     * 订单详情
     * @param array $params
     * @return bool
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function getDetail($params = [])
    {
        $where          = isset($params['where']) ? $params['where'] : ['id' => -1];
        $order          = isset($params['order']) ? $params['order'] : 'id DESC';
        $isDetails      = !empty($params['is_details']) ? true : false;
        $isAddressType  = !empty($params['is_address_type']) ? true : false;
        $row            = $this->where($where)->order($order)->find();

        if (!$row) {
            $this->error = __('Order does not exist');
            return false;
        }

        $row = $row->toArray();
        if ($isDetails) {
            $row['details'] = OrderDetail::where(['order_id' => $row['id']])->select();
        }
        if ($isAddressType) {
            $row['address_type'] = UserAddress::where(['id' => $row['address_id']])->value('type', 0);
        }

        $this->data($row);
        return true;
    }

    /**
     * Name: 用户订单结算
     * Date: 2021/12/18 15:59
     */
    public function settlement($params = [])
    {
        $row = $this->where(['id' => $params['id']])->find();
        if (!$row) {
            $this->error = __('Order does not exist');
            return false;
        }

        if ($row['status'] != 1) {
            $this->error = __('订单状态错误') . __('Status ' . $row['status']);
            return false;
        }

        $total_money    = 0;
        $total_integral = 0;
        $recovery       = Recovery::where(['id' => ['IN', $params['recovery_id']]])->select();
        $data           = [];
        $proportion     = Config::get('site.integral_proportion');

        foreach ($recovery as $k => $v) {
            $i = array_search($v['id'], $params['recovery_id']);
            if ($i !== false) {
                $price          = RecoveryCustom::where(['region_id' => $params['region_id'], 'recovery_id' => $v['id']])->order('id DESC')->value('price', 0);
                $number         = isset($params['number'][$i]) ? $params['number'][$i] : 0;
                $total_price    = $price * $number;
                $integral       = $total_price / 100 * $proportion;

                // 铜类不计算积分
                if (in_array($v['id'], [9, 10])) {
                    $integral = 0;
                }

                $total_money    = $total_money + $total_price;
                $total_integral = $total_integral + $integral;

                $data[] = [
                    'order_id'      => $row['id'],
                    'user_id'       => $row['user_id'],
                    'recycler_id'   => $row['recycler_id'],
                    'recovery_id'   => $v['id'],
                    'title'         => $v['name'],
                    'unit'          => $v['unit'],
                    'price'         => $price,
                    'number'        => $number,
                    'total_price'   => $total_price,
                    'integral'      => $integral,
                    'createtime'    => time(),
                ];
            }
        }

        Db::startTrans();
        try {
            if (!Db::name('OrderDetail')->insertAll($data)) {
                Db::rollback();
                $this->error = __('订单详情添加失败');
                return false;
            }

            if (!$this->where(['id' => $row['id']])->update([
                'status'            => 2,
                'total_money'       => $total_money,
                'total_integral'    => $total_integral,
                'updatetime'        => time(),
                'successtime'       => time()
            ])) {
                Db::rollback();
                $this->error = __('订单状态编辑失败');
                return false;
            }

            Db::commit();
        } catch (ValidateException $e) {
            Db::rollback();
            $this->error = $e->getMessage();
            return false;
        } catch (PDOException $e) {
            Db::rollback();
            $this->error = $e->getMessage();
            return false;
        } catch (\Exception $e) {
            Db::rollback();
            $this->error = $e->getMessage();
            return false;
        }

        User::score($total_integral, $row['user_id'], '回收获得积分');
        return true;
    }

    /**
     * 回收订单
     * @param array $params
     */
    public function addRecycleOrder($params = [])
    {
        if ($params) {
            $result = false;

            $extend = [
                'order_no'  => date('Ymds') . mt_rand(10000, 99999) . Random::numeric(4),
            ];
            // 如果有传递区域ID
            if ($params['region_id']) {
                $regionModel = Region::where('id', $params['region_id'])->find();
                if ($regionModel->status == 0) {
                    $this->error = '片区系统维护中敬请期待';
                    return false; 
                }
            }
            return true;

            $params = array_merge($params, $extend);
            $id     = null;
            Db::startTrans();
            try {
                $validate   = "app\\common\\validate\\Order.add";
                $result     = $this->validateFailException(true)->validate($validate)->allowField(true)->save($params);
                $id         = $this->getLastInsID();
                Db::commit();
            } catch (ValidateException $e) {
                Db::rollback();
                $this->error = $e->getMessage();
                return false;
            } catch (PDOException $e) {
                Db::rollback();
                $this->error = $e->getMessage();
                return false;
            } catch (\Exception $e) {
                Db::rollback();
                $this->error = $e->getMessage();
                return false;
            }

            if ($result !== false) {
                if (
                    $params['region_id']
                    &&
                    $openids = UserRecyclerInfo::where([
                        'region_id' => $params['region_id'],
                        'platform'  => 'wechat',
                        'apptype'   => 'wechat_official_accounts',
                    ])
                    ->field('third.user_id,openid')
                    ->alias('UserRecyclerInfo')
                    ->join('UserThird third', 'third.user_id = UserRecyclerInfo.user_id')
                    ->select()
                ) {
                    $template                   = get_wechat_templates('gzh-mb1');
                    $template['touser']         = ''; // openid
                    $template['miniprogram']    = [
                        'appid'     => isset(Config::get('site.wechat_applet')['app_id']) ? Config::get('site.wechat_applet')['app_id'] : '',
                        'pagepath'  => 'pages/order/order-detail?recycler=1&order_id=' . $id,
                    ];
                    $template['data']           = [
                        'first'     => [
                            'value' => '有新的回收订单,快来接单吧'
                        ],
                        'keyword1'  => [
                            'value' => isset($params['scheduledtime']) ? $params['scheduledtime'] : ''
                        ],
                        'keyword2'  => [
                            'value' => isset($params['address']) ? $params['address'] : ''
                        ],
                        'keyword3'  => [
                            "value" => isset($params['username']) ? $params['username'] : ''
                        ],
                        'keyword4'  => [
                            'value' => isset($params['mobile']) ? $params['mobile'] : ''
                        ],
                        'keyword5' => [
                            'value' => date('Y-m-d H:i:s')
                        ],
                        'remark'    =>[
                            'value' => !empty($params['remarks']) ? $params['remarks'] : '无'
                        ]
                    ];

                    foreach ($openids as $v) {
                        if (!empty($v['openid'])) {
                            $template['touser'] = $v['openid'];

                            try {
                                wechat_factory('officialAccount')->template_message->send($template);
                            } catch (\Exception $e) {
                            }
                        }
                    }
                }

                return true;
            } else {
                $this->error = __('No rows were inserted');
                return false;
            }
        }

        $this->error = __('Parameter %s can not be empty', '');
        return false;
    }

    /**
     * 获取用户订单
     * @param array $params
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public function getList($params = [])
    {
        $where = isset($params['where']) ? $params['where'] : [];
        $order = isset($params['order']) ? $params['order'] : 'id DESC';

        return $this->where($where)->order($order)->paginate();
    }

    public function getWeightTypeList()
    {
        return ['1' => __('Weight_type 1'), '2' => __('Weight_type 2'), '3' => __('Weight_type 3')];
    }

    public function getWeightTypeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['weight_type']) ? $data['weight_type'] : '');
        $list = $this->getWeightTypeList();
        return isset($list[$value]) ? $list[$value] : '';
    }

    public function getImagesAttr($value, $data)
    {
        $data = [];
        if ($value) {
            $value = explode(',', $value);
            foreach ($value as &$v) {
                $data[] = $v ? cdnurl($v, true) : $v;
            }
        }

        return $data;
    }

    public function getStatusList()
    {
        return ['0' => __('Status 0'), '1' => __('Status 1'), '2' => __('Status 2'), '3' => __('Status 3'), '6' => __('Status 6')];
    }

    public function getStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
        $list = $this->getStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }

    public function getCreatetimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['createtime']) ? $data['createtime'] : '');
        return $value && is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }

    public function getDeliverytimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['deliverytime']) ? $data['deliverytime'] : '');
        return $value && is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }

    public function getReceivingtimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['receivingtime']) ? $data['receivingtime'] : '');
        return $value && is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }

    public function getScheduledtimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['scheduledtime']) ? $data['scheduledtime'] : '');
        return $value && is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }

    public function getAccepttimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['accepttime']) ? $data['accepttime'] : '');
        return $value && is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }


    public function getSuccesstimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['successtime']) ? $data['successtime'] : '');
        return $value && is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }

    protected function setScheduledtimeAttr($value)
    {
        return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
    }

    protected function setAccepttimeAttr($value)
    {
        return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
    }

    protected function setSuccesstimeAttr($value)
    {
        return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
    }
}
